/*
 * SpeedoDyno - Speedometer and dynamometer application for Android 
 * Copyright 2013 Guilhem VALENTIN
 * 
 * This file is part of SpeedoDyno
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with SpeedoDyno. If not, see <http://www.gnu.org/licenses/>.
 */
package com.gvalentin.speedodyno;

import java.text.DecimalFormat;

import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;

import com.gvalentin.speedodyno.data.DataLogger;
import com.gvalentin.speedodyno.data.SpeedoDynoData;
import com.gvalentin.speedodyno.listener.SpeedoDynoLocationListener;
import com.gvalentin.speedodyno.util.PreferenceUtil;
import com.gvalentin.speedodyno.util.SpeedUnit;
import com.gvalentin.speedodyno.util.SpeedoDynoMockupInjector;
import com.gvalentin.speedodyno.util.SystemUtil;
import com.gvalentin.speedodyno.view.DynamoBars;
import com.gvalentin.speedodyno.view.Dynamometer;
import com.gvalentin.speedodyno.view.Speedometer;

/**
 * Main activity
 * @author guilhem
 */
public class SpeedoDynoActivity extends Activity implements OnSharedPreferenceChangeListener {
	
	private static final String TAG = SpeedoDynoActivity.class.getSimpleName();
	
	// ID of notification
	private static final int NOTIFICATION_ID = 123;
	
	
	private Notification notification = null;
	private NotificationManager notificationManager = null;

	private static final DecimalFormat rounder0 = new DecimalFormat("#");
	
	// Meters
	private Speedometer speedometer;
	private Dynamometer dynamometer;
	private DynamoBars dynamobars;
	
	// GPS
	private LocationManager lManager;
	private SpeedoDynoLocationListener locationListener;
	
	// Data
	private SpeedoDynoData data;
	
	// Preferences
	private SharedPreferences sharedPreferences;
	
	
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

    	// Remove title bar with application name at top of the screen
        // Must be called before adding content
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        
        // Set view
        setContentView(R.layout.speedodyno);
    	
        // Load preferences
        sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
        
    	// Create and configure data structure
    	initData();
    	
    	// Get and configure meters
		speedometer = (Speedometer) findViewById(R.id.speedometer);
		dynamometer = (Dynamometer) findViewById(R.id.dynamometer);
		dynamobars = (DynamoBars) findViewById(R.id.dynamobars);
		speedometer.configure(sharedPreferences);
		dynamometer.configure(sharedPreferences);
		dynamobars.configure(sharedPreferences);
        
		// Get location manager and listener
        lManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        locationListener = new SpeedoDynoLocationListener(this, lManager);
    }
	
	/** Initialize configuration for data calculation */
	private void initData() {
        int M = PreferenceUtil.getPreference(sharedPreferences, "pref_mass", 110);
        double f = PreferenceUtil.getPreference(sharedPreferences, "pref_f", 0.006d);
        double SCx = PreferenceUtil.getPreference(sharedPreferences, "pref-SCx", 0.09d);
		if (data == null) {
			data = new SpeedoDynoData(M, f, SCx);
		} else {
	        data.configure(M, f, SCx);
		}
	}
	
    /**
     * @see android.app.Activity#onResume()
     */
    @Override
	public void onResume() {
	    super.onResume();
		Log.i(TAG, "onResume()");
		
        // Set up a listener whenever a key changes            
		sharedPreferences.registerOnSharedPreferenceChangeListener(this);
		
        // Keep screen on
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        
        // Add notification
        startNotification();
        
		// Register for location updates
		lManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
		
        // If using the emulator: activate debugging mode
		if (SystemUtil.isEmulator()) {
			Log.d(TAG, "Launching debug mode");
			startDebugMode();
		}
		
		updateScreen();
	}

    /**
     * @see android.app.Activity#onPause()
     */
    @Override
	public void onPause() {
	    super.onPause();
		Log.i(TAG, "onPause()");

        // Remove keep screen on
        getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

		// Remove GPS listener
	    lManager.removeUpdates(locationListener);
	}

    /**
     * @see android.app.Activity#onDestroy()
     */
    @Override
    public void onDestroy() {
	    super.onDestroy();
		Log.i(TAG, "onDestroy()");

        // Stop debug mode
		if (SystemUtil.isEmulator()) {
			stopDebugMode();
		}
		
        // Unregister the listener whenever a key changes            
		sharedPreferences.unregisterOnSharedPreferenceChangeListener(this);    

        // Stop notification
        stopNotification();
    }
    
    
    //
    // Updating location
    //
    
	/** Update current position */
	public void updatePosition(Location location) {
		data.updateLocation(location);
		updateScreen();
		udpateNotification();
		
		// Log data if needed
		if (sharedPreferences.getBoolean("pref_logging", false)) {
			DataLogger.storeLocation(location, data);
		}
	}
	
	/**
	 * Update the elements on screen with current data
	 */
	private void updateScreen() {
		speedometer.setPositionData(data);
		dynamometer.setPositionData(data);
		dynamobars.setPositionData(data);
	}
	
	
    //
    // Mockup data injector
    //
    
	private SpeedoDynoMockupInjector injector = null;
	
	/** Initialize debug mode */
	private void startDebugMode() {
		if (injector == null) {
			injector = new SpeedoDynoMockupInjector(this, locationListener);
			injector.start();
		}
	}
	
	/** Stop debug mode */
	private void stopDebugMode() {
		if (injector != null) {
			injector.stop();
			injector = null;
		}
	}
	
	
    //
    // Notification management
    //

	/** Start notification */
	private void startNotification() {
		// Get notification manager
		if (notificationManager == null) {
			notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
		}
		
		// Create notification
	    final String notificationTicker = getResources().getString(R.string.notification_ticker);
		notification = new Notification(R.drawable.ic_speedodyno, notificationTicker, System.currentTimeMillis());
		
		// Define redirection when clicking on notification
		final PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, SpeedoDynoActivity.class), 0);
		
		// Set title and description
		final double speed = SpeedUnit.toKph(data.getSpeed());
		final String speedStr = rounder0.format(speed);
	    final String notificationTitle = getResources().getString(R.string.notification_title);
	    final String notificationDesc = getResources().getString(R.string.notification_description)
	    		+ " " + speedStr + " km/h";
	    notification.setLatestEventInfo(this, notificationTitle, notificationDesc, pendingIntent);

	    // Set flags
	    notification.flags |= Notification.FLAG_ONGOING_EVENT;
	    
	    // Send notification
	    notificationManager.notify(NOTIFICATION_ID, notification);
	}
	
	/** Update notification */
	private void udpateNotification() {
		if (notification != null && notificationManager != null) {
			final double speed = SpeedUnit.toKph(data.getSpeed());
			final String speedStr = rounder0.format(speed);
			
		    final String notificationTitle = getResources().getString(R.string.notification_title);
		    final String notificationDesc = getResources().getString(R.string.notification_description)
		    		+ " " + speedStr + " km/h";
		    
			notification.when = System.currentTimeMillis();
		    notification.setLatestEventInfo(this, notificationTitle, notificationDesc, notification.contentIntent);
		    notificationManager.notify(NOTIFICATION_ID, notification);
		}
	}
	
	/** Stop notification */
	private void stopNotification() {
		if (notificationManager == null) {
			notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
		}
	    notificationManager.cancel(NOTIFICATION_ID); 
	    notification = null;
	    notificationManager.cancelAll();
	}
	
	
    //
    // Menu management
    //
    
    /**
     * Called to create options menu
     * @see android.app.Activity#onCreateOptionsMenu(android.view.Menu)
     */
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.menu, menu);
        return true;
    }
    
    /**
     * Item chosen in menu
     * @see android.app.Activity#onOptionsItemSelected(android.view.MenuItem)
     */
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle item selection
        switch (item.getItemId()) {
        
            case R.id.settings:
            	startActivity(new Intent(this, SpeedoDynoPreferences.class));
                return true;
            /*
            case R.id.vehicle:
            	// TODO
                return true;
            */
            case R.id.quit:
                finish();
                return true;
                
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    //
    // Popup menu management
    //

	/**
	 * Called when clicking on 3 dots button
	 */
	public void showPopup(View v) {
        openOptionsMenu();
	}
    
	
    //
    // Preferences management
    //

	/**
	 * Action performed when a preference is changed
	 */
    @Override
	public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
    	Log.d(TAG, "onSharedPreferenceChanged(" + key + ")");
    	
    	// Refresh data calculator configuration
    	if ("pref_mass".equals(key) || "pref_f".equals(key) || "pref_SCx".equals(key)) {
        	initData();
    	}
    	
    	// Refresh meters
		speedometer.onPreferenceChanged(sharedPreferences, key);
		dynamometer.onPreferenceChanged(sharedPreferences, key);
		dynamobars.onPreferenceChanged(sharedPreferences, key);
	}
}